Skip to content

Add supplementary material validations for SPS 1.10#1129

Draft
Copilot wants to merge 3 commits intomasterfrom
copilot/create-validations-supplementary-material
Draft

Add supplementary material validations for SPS 1.10#1129
Copilot wants to merge 3 commits intomasterfrom
copilot/create-validations-supplementary-material

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 13, 2026

O que esse PR faz?

Implementa validações para <supplementary-material> e <sec sec-type="supplementary-material"> conforme SPS 1.10, cobrindo 7 de 10 regras (70%):

Regra Validação Nível
1 @id em <supplementary-material> CRITICAL
2 <label> em <supplementary-material> (fix: usava label do media) CRITICAL
3 <title> em <sec sec-type="supplementary-material"> CRITICAL
4 Proibição de <inline-supplementary-material> ERROR
5 Presença de <graphic> ou <media> WARNING
7 Unicidade de @id ERROR

Corrige bug no modelo onde media.data sobrescrevia o label do <supplementary-material> — novo campo suppl_label preserva o valor original. Corrige teste test_validate_full_workflow que falhava por None em resultados de validação.

Onde a revisão poderia começar?

packtools/sps/validation/supplementary_material.py — contém toda a lógica de validação nova.

Como este poderia ser testado manualmente?

python -m pytest tests/sps/validation/test_supplementary_material.py tests/sps/models/test_supplementary_material.py -v

27 testes (16 validação + 11 modelo), todos passando.

Algum cenário de contexto que queira dar?

Modelo (supplementary_material.py): SupplementaryMaterial.data faz base_data.update(self.media.data) que sobrescreve label/caption com os valores do <media> (geralmente None). Campos suppl_label e suppl_caption foram adicionados para preservar os valores do <supplementary-material>.

Validações que retornam None: Métodos como validate_transcript() em accessibility_data.py retornam None para casos não aplicáveis. O xml_validator.py já filtra com if not item: continue. O teste test_validate_full_workflow foi corrigido para seguir o mesmo padrão.

Screenshots

N/A

Quais são tickets relevantes?

N/A

Referências

Original prompt

This section details on the original issue you should resolve

<issue_title>Criar validações para o elemento </issue_title>
<issue_description>## Objetivo

Implementar validações para o elemento <supplementary-material> e a seção <sec sec-type="supplementary-material"> conforme a especificação SPS 1.10, aumentando a conformidade de X% para 70% (7 de 10 regras).

Nota: Algumas validações para <supplementary-material> podem já estar parcialmente implementadas no repositório. Este Issue visa reavaliar, complementar e garantir cobertura completa das regras SPS 1.10.


Contexto

Material suplementar corresponde a todo conteúdo enviado separadamente do PDF do documento que complementa o trabalho publicado. No XML, deve ser representado por uma seção <sec sec-type="supplementary-material"> contendo elementos <supplementary-material> individuais. Validações corretas garantem presença de elementos obrigatórios, estrutura adequada, e conformidade com recomendações PMC/JATS.

Conformidade atual: X de 10 regras implementadas (X%)
Meta após implementação: 7 de 10 regras (70%)


Documentação SPS

Referência oficial: https://docs.google.com/document/d/1GTv4Inc2LS_AXY-ToHT3HmO66UT0VAHWJNOIqzBNSgA/edit?tab=t.0#heading=h.supplementarymaterial

Regras principais conforme SPS 1.10:

  1. Ocorrência:

    • <supplementary-material> pode aparecer zero ou mais vezes em <sec> e <article-meta>
    • <sec sec-type="supplementary-material"> deve ser a última seção de <body> ou aparecer em <back>
  2. Atributos obrigatórios:

    • @sec-type="supplementary-material" em <sec> (obrigatório)
    • @id em <supplementary-material> (obrigatório)
    • Atributos em <media>: @id, @mime-type, @mime-subtype, @xlink:href (obrigatórios)
    • Atributo em <graphic>: @xlink:href (obrigatório)
  3. Elementos obrigatórios:

    • <sec sec-type="supplementary-material"> requer <title> (obrigatório)
    • <supplementary-material> requer <label> (obrigatório)
  4. Estrutura:

    • Seção <sec sec-type="supplementary-material"> como container
    • Um elemento <supplementary-material> para cada item suplementar
    • Dentro de <supplementary-material>:
      • <graphic> para figuras
      • <media> para outros tipos (PDF, Word, Excel, vídeo, etc.)
  5. Elementos opcionais:

    • <caption> com <title> (opcional em <supplementary-material>)
  6. Restrições:

    • Proibido: uso de <inline-supplementary-material>
  7. Regras de links externos:

    • Links externos não dispensam envio do arquivo no pacote
    • Arquivo deve estar no pacote e marcado como <supplementary-material>
    • Link pode ser mantido como <ext-link> adicional no texto
  8. Distinções importantes:

    • Dataset: não é material suplementar → Declaração de Disponibilidade de Dados
    • Conteúdo no PDF: não é material suplementar → marcar com elemento semântico apropriado
    • Apêndice/Anexo: usar <app-group> e <app>, não material suplementar

Regras a Implementar

P0 – Críticas (implementar obrigatoriamente)

# Regra Nível Descrição
1 Validar presença de @id em <supplementary-material> CRITICAL O atributo @id é obrigatório em <supplementary-material>
2 Validar presença de <label> em <supplementary-material> CRITICAL O elemento <label> é obrigatório em cada <supplementary-material>
3 Validar presença de <title> em <sec sec-type="supplementary-material"> CRITICAL O elemento <title> é obrigatório em <sec sec-type="supplementary-material">
4 Validar ausência de <inline-supplementary-material> ERROR O uso de <inline-supplementary-material> não é permitido

P1 – Importantes (implementar se possível)

# Regra Nível Descrição
5 Validar presença de conteúdo (<graphic> ou <media>) WARNING <supplementary-material> deve conter <graphic> (para figuras) ou <media> (para outros tipos)
6 Validar presença de <sec sec-type="supplementary-material"> quando há <supplementary-material> WARNING Materiais suplementares devem estar dentro de <sec sec-type="supplementary-material">
7 Validar unicidade de @id em <supplementary-material> ERROR Cada <supplementary-material> deve ter um @id único

P2 – Futuras (fora do escopo deste Issue)

# Regra Motivo de exclusão
8 Validar que arquivo existe no pacote Alta complexidade - requer acesso ao sistema de arquivos
9 Validar posicionamento (última seção de body ou em back) Média complexidade - requer análise de ordem de elementos irmãos
10 Validar que conteúdo não é dataset Alta complexidade - requer análise semântica de conteúdo

Arquivos a Criar/Modificar

Avaliar existentes (podem ter validações parciais):

  • `packtoo...

✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI and others added 2 commits March 13, 2026 14:34
- Add validate_id: @id presence in supplementary-material (CRITICAL)
- Add validate_sec_title: <title> in sec (CRITICAL)
- Add validate_content: <graphic>/<media> presence (WARNING)
- Add validate_id_uniqueness: unique @id values (ERROR)
- Update inline error level from CRITICAL to ERROR
- Fix validate_label to use suppl_label (preserved from model)
- Add suppl_label, suppl_caption, has_content to model data
- Update rules JSON with new error level configs
- Rewrite tests: 16 tests covering all validations

Co-authored-by: robertatakenaka <505143+robertatakenaka@users.noreply.github.com>
Co-authored-by: robertatakenaka <505143+robertatakenaka@users.noreply.github.com>
Copilot AI changed the title [WIP] Implement validations for supplementary-material element Add supplementary material validations for SPS 1.10 Mar 13, 2026
Copilot AI requested a review from robertatakenaka March 13, 2026 14:37
Copy link
Copy Markdown
Collaborator

@Rossi-Luciano Rossi-Luciano left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: validações de supplementary_material.py não produzem resultados no pipeline

Identificado via análise cruzada de xml_validations.py, xml_validator.py e relatório CSV gerado pelo pipeline de validação do upload3/scms-upload com XML artificial de cobertura total do módulo.


Diagnóstico

O XML artificial continha elementos <supplementary-material> cobrindo todos os casos de validação do módulo (validate_id, validate_sec_type, validate_label, validate_not_in_app_group, validate_content, validate_prohibited_inline, validate_position, validate_sec_title, validate_id_uniqueness). O asset checker e o módulo de acessibilidade processaram corretamente todos os elementos — confirmando que o XML foi parseado com sucesso. No entanto, nenhuma entrada com group="supplementary-material" apareceu no CSV. O grupo foi silenciosamente descartado.


Problema 1 — Causa raiz: "supplementary_materials_rules" ausente de get_default_rules()

Em xml_validations.py, validate_supplementary_materials acessa:

rules.update(params["supplementary_materials_rules"])

Se a chave "supplementary_materials_rules" não estiver registrada em xml_validator_rules.py / get_default_rules(), a linha levanta KeyError na primeira iteração do gerador. Em xml_validator.py, get_validation_results captura a exceção no bloco except externo e descarta o grupo inteiro — sem registrar nenhum resultado no CSV.

O comentário # TODO presente na função validate_supplementary_materials confirma que a integração estava incompleta ao ser mergeada.

Correção: adicionar "supplementary_materials_rules" ao dicionário retornado por get_default_rules() em xml_validator_rules.py, com o conteúdo definido em supplementary_material_rules.json:

"supplementary_materials_rules": {
    "sec_type_error_level": "CRITICAL",
    "position_error_level": "CRITICAL",
    "label_error_level": "CRITICAL",
    "app_group_error_level": "CRITICAL",
    "inline_error_level": "ERROR",
    "id_error_level": "CRITICAL",
    "sec_title_error_level": "CRITICAL",
    "content_error_level": "WARNING",
    "id_uniqueness_error_level": "ERROR",
    "mime_types_and_subtypes": [
        {"mimetype": "video", "mime-subtype": "mp4"},
        {"mimetype": "audio", "mime-subtype": "mp3"},
        {"mimetype": "application", "mime-subtype": "zip"},
        {"mimetype": "application", "mime-subtype": "pdf"},
        {"mimetype": "application", "mime-subtype": "xlsx"}
    ],
    "mime_type_error_level": "CRITICAL",
    "media_attributes_error_level": "CRITICAL",
    "parent_suppl_mat_expected": ["app-group", "app"],
}

Após a correção, remover o comentário # TODO de validate_supplementary_materials.


Problema 2 — Campo obtained incorreto em validate_sec_type()

Em supplementary_material.py (validação), validate_sec_type define:

obtained=self.data.get("parent_tag"),

O campo obtained deve refletir o valor encontrado para o atributo sendo validado — neste caso @sec-type. parent_tag é a tag do elemento pai (sempre "sec" neste contexto), não o valor de @sec-type. Além disso, quando sec_type=None (atributo ausente), a mensagem de advice exibe literalmente "None":

In <sec sec-type="None"><supplementary-material> replace "None" with "supplementary-material".

Correção:

# antes
obtained=self.data.get("parent_tag"),

# depois
obtained=sec_type,

E ajustar o advice para tratar sec_type=None de forma descritiva:

sec_type_display = sec_type if sec_type else "(ausente)"
advice=f'In <sec sec-type="{sec_type_display}"><supplementary-material> '
       f'replace "{sec_type_display}" with "supplementary-material".',

Problema 3 — visual_elem incorreto quando <supplementary-material> não tem conteúdo

Em supplementary_material.py (model), SupplementaryMaterial.data define:

"visual_elem": "media" if self.media else "graphic",

Quando nem self.media nem self.graphic estão presentes (caso has_content=False), visual_elem recebe "graphic" em vez de None. O valor é enganoso e pode mascarar o diagnóstico de validate_content.

Correção:

"visual_elem": "media" if self.media else ("graphic" if self.graphic else None),

Problema 4 — Shadowing de variável em validate_position()

Em XmlSupplementaryMaterialValidation.validate_position(), a variável sections é declarada com xpath e depois sobrescrita com findall:

sections = self.xml_tree.xpath('.//sec[@sec-type="supplementary-material"]')
if not sections:
    return
# ...
if article_body is not None:
    sections = article_body.findall("sec")  # ← sobrescreve sections

Não causa bug funcional no código atual, mas é frágil: qualquer refatoração que referencie sections após o if article_body bloco assumindo o valor do xpath obterá resultado incorreto.

Correção: usar nomes de variável distintos:

suppl_sections = self.xml_tree.xpath('.//sec[@sec-type="supplementary-material"]')
if not suppl_sections:
    return
# ...
if article_body is not None:
    body_sections = article_body.findall("sec")
    if body_sections and body_sections[-1].get("sec-type") == "supplementary-material":
        is_last_in_body = True

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Criar validações para o elemento <supplementary-material>

3 participants